package ProjectoX;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.TexturePaint;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.net.URL;
import java.util.Vector;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Nivel extends Canvas implements KeyListener {

	private static final long serialVersionUID = 1L;
	final protected int ColumnasNivel = 10;
	final protected int AnchoC = 50;
	protected final int SPEED = 10;
	protected Vector<Componente> misComponentes;
	protected Vector<Componente> AuxmisComponentes;
	protected Vector<Personaje> misEnemigos;
	protected Vector<Personaje> AuxmisEnemigos;
	protected Vector<Componente> misPowerUp;
	protected Mario miMario;
	protected Mapa miMapa;
	protected SpriteCache spriteCache;
	protected SoundCache soundCache;
	protected BufferStrategy strategy;
	protected JPanel panel;
	protected JLabel jLabel1;
	private BufferedImage fondo;
	private boolean ingresarEne;
	private boolean ingresarPie;
	private boolean ingresarMon;
	private boolean ingresarPowerUp;
	private boolean ingresarVida;
	private boolean deboCrecer;
	private boolean deboDisparar;
	private boolean deboDesDisparar;
	private boolean deboDesCrecer;
	private boolean activoBomba;
	private boolean teclasActivadas = true;
	protected boolean gameEnded = false;
	protected boolean gameWined = false;
	private int Vidas;
	private int Puntaje;
	protected int Alto;
	protected int Ancho;
	protected long usedTime;
	
	public Nivel () {
		Puntaje = 0;
		Vidas = 1;
		ingresarVida = true;
		spriteCache = new SpriteCache();
		soundCache = new SoundCache();
		miMapa = new Mapa(this);
		Alto = miMapa.getPantalla().getAncho();
		Ancho = miMapa.getPantalla().getAlto();
		JFrame ventana = new JFrame("Mario");

		panel=new JPanel();

				setBounds(0,0,Ancho,Alto);
				panel.setPreferredSize(new Dimension(Alto,Ancho));
				panel.setLayout(null);
				panel.add(this);
				panel.setBackground(new Color(160, 170, 255));
				ventana.getContentPane().add(panel);
				panel.setOpaque(false);



		ventana.setBounds(0,0,Alto,Ancho);
		ventana.setVisible(true);
		ventana.addWindowListener( new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});
		ventana.setResizable(false);
		createBufferStrategy(2);
		strategy = getBufferStrategy();
		addKeyListener(this);
	    setIgnoreRepaint(true);
	    requestFocus();
	}

	public void inicializarNivel() {
		misEnemigos = new Vector<Personaje> ();
		AuxmisEnemigos = new Vector<Personaje> ();
		misComponentes = new Vector<Componente> ();
		AuxmisComponentes = new Vector<Componente> ();
		misPowerUp = new Vector<Componente> ();
		ingresarEne = true;
		ingresarPie = true;
		ingresarMon = true;
		ingresarPowerUp = true;
		miMario = new Mario(this);
		for (int i = 0; i < miMapa.getComponentes().length; i++) {
			for (int j = 0; j < miMapa.getComponentes()[0].length; j++) {
				if (miMapa.getComponentes()[i][j] != null)
					misComponentes.add(miMapa.getComponentes()[i][j]);
			}
		}
		for (int i = 0; i < miMapa.getEnemigos().length; i++) {
			for (int j = 0; j < miMapa.getEnemigos()[0].length; j++) {
				if (miMapa.getEnemigos()[i][j] != null)
					misEnemigos.add(miMapa.getEnemigos()[i][j]);
			}
		}
	}
	
	public void actualizarNivel() {
		actualizarMario();
		if (activoBomba) {
			activoBomba = false;
			int i = 0;
			while (i < misEnemigos.size()) {
				Personaje m = (Personaje) misEnemigos.get(i);
				int x = Math.abs(m.getPos().getX()-miMario.getPos().getX());
				if (x<300)
					misEnemigos.get(i).remove();
				i++;
			}
		}
		int i = 0;
		while (i < misEnemigos.size()) {
			Personaje m = (Personaje) misEnemigos.get(i);
			if (m.isMarkedForRemoval())
				misEnemigos.remove(i);
			else {
				int x = Math.abs(m.getPos().getX()-miMario.getPos().getX());
				if (x<800)
					m.actuar();
				i++;
			}
		}
		i = 0;
		while (i < misComponentes.size()) {
			Componente m = (Componente) misComponentes.get(i);
			if (m.isMarkedForRemoval()){
				miMapa.borrarComponente(m);
				misComponentes.remove(i);
			}
			else {
				int x = Math.abs(m.getPos().getX()-miMario.getPos().getX());
				if (x<300)
					m.actuar();
				i++;
			}
				
		}
		i = 0;
		while (i < AuxmisEnemigos.size()) {
			misEnemigos.add(AuxmisEnemigos.get(i));
			i++;
		}
		AuxmisEnemigos.removeAllElements();
		ingresarEne = true;
		
		i = 0;
		while (i < AuxmisComponentes.size()) {
			misComponentes.add(AuxmisComponentes.get(i));
			i++;
		}
		AuxmisComponentes.removeAllElements();
		ingresarPie = true;
		ingresarMon = true;
		
		
		i = 0;
		while (i < misPowerUp.size()) {
			Componente m = (Componente) misPowerUp.get(i);
			if (m.isMarkedForRemoval()){
				misPowerUp.remove(i);
			}
			else {
				int x = Math.abs(m.getPos().getX()-miMario.getPos().getX());
				if (x>330)
					m.remove();
				else
					m.actuar();
				i++;
			}
				
		}
		ingresarPowerUp = true;
		if (miMario.isMarkedForRemoval())
			gameOver();
		else
			miMario.actuar();
	}

	private void actualizarMario() {
		if (deboCrecer) {
			Posicion P = miMario.getPos();
			miMario = new MarioGrande(this);
			miMario.setPos(new Posicion(P.getX(), P.getY()-19, P.getAncho(), P.getAlto()+19));
			miMario.setPosBase(P.getY()-19);
			deboCrecer = false;
			getSoundCache().playSound("Sonidos/smw_powerup.wav");
		} else
		if (deboDisparar) {
			Posicion P = miMario.getPos();
			miMario = new MarioDisparo(this);
			miMario.setPos(new Posicion(P.getX(), P.getY(), P.getAncho(), P.getAlto()));
			miMario.setPosBase(P.getY());
			deboDisparar = false;
			getSoundCache().playSound("Sonidos/smw_powerup.wav");
		} else
		if (deboDesDisparar) {
			Posicion P = miMario.getPos();
			miMario = new MarioGrande(this);
			miMario.setPos(new Posicion(P.getX(), P.getY()-40, P.getAncho(), P.getAlto()));
			deboDesDisparar = false;
			getSoundCache().playSound("Sonidos/smw_transform.wav");
		} else
		if (deboDesCrecer) {
			Posicion P = miMario.getPos();
			miMario = new Mario(this);
			miMario.setPos(new Posicion(P.getX(), P.getY()-40, P.getAncho(), P.getAlto()-19));
			deboDesCrecer = false;
			getSoundCache().playSound("Sonidos/smw_transform.wav");
		}
			
	}

	public void ciclo() {
		usedTime=1000;
		inicializarNivel();
		while (isVisible() && !gameEnded && !gameWined) {
			long startTime = System.currentTimeMillis();
			actualizarNivel();
			controlarColisiones();
			paintWorld();
			usedTime = System.currentTimeMillis()-startTime;
			try {
				Thread.sleep(SPEED);
			}
			catch (InterruptedException e) {}
		}
		if (gameEnded) {
			getSoundCache().playSound("Sonidos/musicGameOver.midi");
			paintGameOver();
		}
		else {
			paintGameWin();
		}
	}

	public void controlarColisiones() {
        Rectangle playerBounds = miMario.getBounds();
        for (int m = 0; m < misComponentes.size(); m++) {
        	Componente Ca1 = (Componente) misComponentes.get(m);
        	Rectangle Cr1 = Ca1.getBounds();
        	if (Cr1.intersects(playerBounds))
        		miMario.colision(Ca1);
        	for (int i = 0; i < misEnemigos.size(); i++) {
        		Enemigo Ea1 = (Enemigo) misEnemigos.get(i);
        		Rectangle Er1 = Ea1.getBounds();
        		if (Er1.intersects(playerBounds)) {
        			miMario.colision(Ea1);
        		}
        		if (Cr1.intersects(Er1))
        			Ea1.colision(Ca1);
        		for (int j = i+1; j < misEnemigos.size(); j++) {
        			Enemigo a2 = (Enemigo)misEnemigos.get(j);
        			Rectangle r2 = a2.getBounds();
        			if (Er1.intersects(r2)) {
        				Ea1.colision(a2);
        				a2.colision(Ea1);
        			}
    			}
            	for (int j = 0; j < misPowerUp.size(); j++) {
            		PowerUpMovil Pa1 = (PowerUpMovil) misPowerUp.get(j);
            		Rectangle Pr1 = Pa1.getBounds();
            		if (Pr1.intersects(Cr1)) {
            			Pa1.colision(Ca1);
            		}
            		if (Pr1.intersects(playerBounds)) {
            			miMario.colision(Pa1);	
            		}
            		if (Pr1.intersects(Er1))
            			Pa1.colision(Ea1);
            	}
        	}
        }
	}

	public Mario getPersonaje() {
		return miMario;
	}

	public Mapa getMapa() {
		return miMapa;
	}
	
    public SoundCache getSoundCache() {
        return soundCache;
    }
    
    public SpriteCache getSpriteCache() {
    	return spriteCache;
    }

	public void keyPressed(KeyEvent e) {
		if (teclasActivadas)
			miMario.teclaPresionada(e);
	}

	public void keyReleased(KeyEvent e) {
		if (teclasActivadas)
			miMario.teclaSoltada(e);
	}

	public void keyTyped(KeyEvent e) {

	}

    public BufferedImage loadImage(String nombre) {
        URL url=null;
        try {
        	url = getClass().getClassLoader().getResource(nombre);
        	return ImageIO.read(url);
        }
        catch (Exception e) {
        	System.out.println("No se pudo cargar la imagen " + nombre +" de "+url);
        	System.out.println("El error fue : "+e.getClass().getName()+" "+e.getMessage());
        	System.exit(0);
        	return null;
        }
    }

    public void paintWorld() {
    	Graphics2D g = (Graphics2D)strategy.getDrawGraphics();
    	fondo = spriteCache.getSprite("Fondo/arctis.png");
	    g.setPaint(new TexturePaint(fondo, new Rectangle(0,0,498,500)));
	    g.fillRect(0,0,getWidth(),getHeight());
        panel.paint(g);
        
        int q = 0;
		while (q < misEnemigos.size()) {
			Enemigo e = (Enemigo) misEnemigos.get(q);
			e.paint(g);
			q++;
		}  
        
        
        if ((miMario.getPos().getX()>=320)&&(miMario.getPos().getX()<=12000)) {      //SE PINTA DE ESTA MANERA EN TODOS LOS CASOS MENOS CUANDO ESTAMOS POSICIONADOS
        	int ini = miMario.getPos().getX();	//AL PRINCIPIO O AL FINAL
            ini =(ini -320);
            int z = ini;
            ini = ini/AnchoC;
            if (miMario.getPos().getX() % AnchoC !=0)
            	ini++;
            int fin = ini + ColumnasNivel;
    		for (int i = 0; i < misComponentes.size(); i++) {
            		Componente C = (Componente) misComponentes.get(i);
            		if ((C!= null) && (C.getColumna()>=ini) &&(C.getColumna()<fin)) {
                		C.setLocalization(C.getPos().getX()-z);
            			C.paint(g);
            		}
            	}
    		for (int i = 0; i < misPowerUp.size(); i++) {
        		Componente C = (Componente) misPowerUp.get(i);
        		if (C!=null) {
            		C.setLocalization(C.getPos().getX()-z);
        			C.paint(g);
        		}
        	}
            }
        
        
        else 
        	if (miMario.getPos().getX()<320){
        		for (int i = 0; i < ColumnasNivel; i++) {  //UTILIZAMOS ESTA PARTE DEL CODIGO PARA PINTAR LA PANTALLA CUANDO 
        			for (int j = 0; j < 10; j++) {			//ESTAMOS AL PRINCIPIO DEL NIVEL
        				Componente C = (Componente) miMapa.getComponentes()[i][j];
        				if (C!= null) {
        					C.setLocalization(C.getPos().getX());
        					C.paint(g);
        				}
        			}
        		}
        	}
        	else {
        		for (int i = 90; i < ColumnasNivel; i++) {  //UTILIZAMOS ESTA PARTE DEL CODIGO PARA PINTAR LA PANTALLA CUANDO 
        			for (int j = 0; j < 10; j++) {			//ESTAMOS AL FINAL DEL NIVEL
        				Componente C = (Componente) miMapa.getComponentes()[i][j];
        				if (C!= null) {
        					C.setLocalization(C.getPos().getX());
        					C.paint(g);
        				}
        			}
        		}
        		
        	}
        miMario.paint(g);
        paintPuntaje();
        strategy.show();
	}

	public void paintGameOver() {
		Graphics2D g = (Graphics2D)strategy.getDrawGraphics();
		g.setColor(Color.black);
        g.fillRect(0,0,getWidth(),getHeight());
		g.setColor(Color.white);
		g.setFont(new Font("ARIAL", Font.BOLD, 30));
		g.drawString("GAME OVER",Ancho/2-80,Alto/2);
		g.setFont(new Font("ARIAL", Font.BOLD, 20));
		g.drawString("PUNTAJE: "+Puntaje,Ancho/2-45,Alto/2+50);
		strategy.show();
  }
	
	
	public void paintGameWin() {
		Graphics2D g = (Graphics2D)strategy.getDrawGraphics();
		g.setColor(Color.black);
        g.fillRect(0,0,getWidth(),getHeight());
		g.setColor(Color.white);
		g.setFont(new Font("ARIAL", Font.BOLD, 30));
		g.drawString("YOU WIN",Ancho/2-80,Alto/2);
		g.setFont(new Font("ARIAL", Font.BOLD, 20));
		g.drawString("PUNTAJE: "+Puntaje,Ancho/2-80,Alto/2+50);
		strategy.show();
  }	
	
	public void paintPuntaje() {
		Graphics2D g = (Graphics2D)strategy.getDrawGraphics();
		g.setColor(Color.black);
		g.setFont(new Font("ARIAL", Font.BOLD, 10));
		g.drawString("PUNTAJE: "+Puntaje+"",420,15);
		int x = 15;
		for (int i = 0; i<Vidas; i++) {
			g.drawImage( spriteCache.getSprite("Fondo/tux-life.png"), x*i,5, this );	
		}
		strategy.show();
  }	
    
    public void addEnemigo(Enemigo E) {
    	if (ingresarEne) {
    		AuxmisEnemigos.add(E);
    		ingresarEne = false;
    	}	
    }

    public void addPiedra(Componente C) {
    	if (ingresarPie) {
    		misComponentes.add(C);
    		ingresarPie = false;
    	}	
    }
    
    public void addMoneda(Componente C) {
    	if (ingresarMon) {
    		misComponentes.add(C);
    		ingresarMon = false;
    	}	
    }

    public void addPowerUp(Componente C) {
    	if (ingresarPowerUp) {
    		misPowerUp.add(C);
    		ingresarPowerUp = false;
    	}	
    }
    
    public void deboCrecer(){
    	deboCrecer = true;
    }

    public void deboDesCrecer(){
    	deboDesCrecer = true;
    }
    
    public void deboDisparar(){
    	deboDisparar = true;
    }

    public void deboDesDisparar(){
    	deboDesDisparar = true;
    }
    
    public void activoBomba () {
    	activoBomba = true;
    }
    
    public void incrementarPuntaje(int Sum) {
    	Puntaje += Sum;
    }
    
    public void incrementarVida() {
    	if (ingresarVida) {
    		Vidas++;
    		ingresarVida = false;
    		getSoundCache().playSound("Sonidos/smw_1-up.wav");
    	}
    		
    }
    
    public boolean ingresoVida() {
    	return ingresarVida;
    }
    
    public boolean gameEnded (){
    	return gameEnded;
    }
    
	public void gameOver() {
		Vidas--;
		if (Vidas <= 0)
			gameEnded = true;
		else {
			getSoundCache().playSound("Sonidos/smw_death.wav");
			miMapa = new Mapa(this);
			inicializarNivel();
		}
	}

	public void gameWiner() {
		gameWined = true;
	}

	public void Animar() {
		if (teclasActivadas) {
			teclasActivadas = false;
			miMario.GetMov().setMovHorizontal(0);
			new Reminder (14, this);
			int x = 400 - miMario.getPos().getY();
			for (int i = 0; i<x; i++) {
				Puntaje++;
				paintWorld();				
				try {
					Thread.sleep(1);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}

			}	
		}
		
		
	}
    
}
